streamlit-nightly 1.44.2.dev20250427__py3-none-any.whl → 1.45.1.dev20250429__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- streamlit/auth_util.py +1 -1
- streamlit/commands/experimental_query_params.py +1 -1
- streamlit/components/v1/custom_component.py +1 -1
- streamlit/config.py +18 -4
- streamlit/delta_generator.py +0 -3
- streamlit/deprecation_util.py +1 -1
- streamlit/elements/arrow.py +6 -6
- streamlit/elements/code.py +15 -0
- streamlit/elements/deck_gl_json_chart.py +4 -4
- streamlit/elements/dialog_decorator.py +0 -1
- streamlit/elements/doc_string.py +18 -26
- streamlit/elements/image.py +8 -9
- streamlit/elements/lib/built_in_chart_utils.py +8 -8
- streamlit/elements/lib/column_config_utils.py +1 -1
- streamlit/elements/lib/column_types.py +3 -0
- streamlit/elements/lib/image_utils.py +25 -26
- streamlit/elements/lib/pandas_styler_utils.py +7 -7
- streamlit/elements/map.py +2 -2
- streamlit/elements/plotly_chart.py +5 -5
- streamlit/elements/vega_charts.py +8 -8
- streamlit/elements/widgets/audio_input.py +1 -1
- streamlit/elements/widgets/button.py +7 -6
- streamlit/elements/widgets/button_group.py +5 -11
- streamlit/elements/widgets/camera_input.py +1 -1
- streamlit/elements/widgets/chat.py +1 -3
- streamlit/elements/widgets/checkbox.py +1 -1
- streamlit/elements/widgets/color_picker.py +1 -1
- streamlit/elements/widgets/data_editor.py +1 -1
- streamlit/elements/widgets/file_uploader.py +6 -7
- streamlit/elements/widgets/multiselect.py +1 -5
- streamlit/elements/widgets/number_input.py +10 -13
- streamlit/elements/widgets/radio.py +1 -5
- streamlit/elements/widgets/select_slider.py +3 -7
- streamlit/elements/widgets/selectbox.py +1 -5
- streamlit/elements/widgets/slider.py +2 -2
- streamlit/elements/widgets/text_widgets.py +2 -2
- streamlit/elements/widgets/time_widgets.py +2 -6
- streamlit/error_util.py +1 -1
- streamlit/external/langchain/streamlit_callback_handler.py +4 -0
- streamlit/git_util.py +2 -2
- streamlit/hello/dataframe_demo.py +2 -2
- streamlit/logger.py +5 -5
- streamlit/navigation/page.py +1 -1
- streamlit/proto/Code_pb2.py +4 -3
- streamlit/proto/Code_pb2.pyi +9 -1
- streamlit/runtime/app_session.py +9 -9
- streamlit/runtime/caching/cached_message_replay.py +1 -1
- streamlit/runtime/caching/hashing.py +3 -4
- streamlit/runtime/caching/legacy_cache_api.py +1 -1
- streamlit/runtime/caching/storage/dummy_cache_storage.py +1 -1
- streamlit/runtime/caching/storage/local_disk_cache_storage.py +2 -2
- streamlit/runtime/connection_factory.py +8 -8
- streamlit/runtime/context.py +1 -1
- streamlit/runtime/forward_msg_queue.py +10 -10
- streamlit/runtime/metrics_util.py +2 -2
- streamlit/runtime/pages_manager.py +1 -3
- streamlit/runtime/runtime_util.py +1 -1
- streamlit/runtime/scriptrunner/exec_code.py +1 -1
- streamlit/runtime/scriptrunner/magic.py +3 -4
- streamlit/runtime/scriptrunner/script_runner.py +2 -2
- streamlit/runtime/state/common.py +2 -2
- streamlit/runtime/state/session_state.py +2 -2
- streamlit/static/index.html +1 -1
- streamlit/static/static/js/{ErrorOutline.esm.BGxEEkBO.js → ErrorOutline.esm.BJh3F07v.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.BIvOCWXm.js → FileDownload.esm.BpUJskrZ.js} +1 -1
- streamlit/static/static/js/{FileHelper.CJg2rGQf.js → FileHelper.DKXMFthp.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.BKO5MjJ1.js → FormClearHelper.CcbGU8qM.js} +1 -1
- streamlit/static/static/js/{Hooks.Ch4fyM-d.js → Hooks.CyZIh6nK.js} +1 -1
- streamlit/static/static/js/{InputInstructions.BVG0uTsn.js → InputInstructions.nbkV1h_d.js} +1 -1
- streamlit/static/static/js/{ProgressBar.qtOeZiGm.js → ProgressBar.DeCaMWV9.js} +1 -1
- streamlit/static/static/js/{RenderInPortalIfExists.BNrfjgR-.js → RenderInPortalIfExists.D_SwWwav.js} +1 -1
- streamlit/static/static/js/{Toolbar.DLYoM1Wd.js → Toolbar.BAN-49vk.js} +1 -1
- streamlit/static/static/js/{base-input.CMZL3Njp.js → base-input.BGFZMByD.js} +1 -1
- streamlit/static/static/js/{checkbox.Bg2c6brb.js → checkbox.B_-BK4qi.js} +1 -1
- streamlit/static/static/js/{createSuper.feapqlxC.js → createSuper.BxyEvip2.js} +1 -1
- streamlit/static/static/js/{data-grid-overlay-editor.CPfW2LFj.js → data-grid-overlay-editor.DmJscfNY.js} +1 -1
- streamlit/static/static/js/{downloader.DzXny7Ld.js → downloader.Cv_h08Sg.js} +1 -1
- streamlit/static/static/js/{es6.0m8Dphx5.js → es6.BEoJ6t5B.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.cmKtyqx-.js → iframeResizer.contentWindow.DnBVl60m.js} +1 -1
- streamlit/static/static/js/{index.BOLpjodc.js → index.0QGnttRw.js} +1 -1
- streamlit/static/static/js/{index.cslPh4fD.js → index.7LZxcVw4.js} +1 -1
- streamlit/static/static/js/{index.C-FM6HWK.js → index.BBlDwZ3d.js} +5 -5
- streamlit/static/static/js/{index.CrKlAaBP.js → index.BCUsUBov.js} +1 -1
- streamlit/static/static/js/{index.GK7AGRO0.js → index.BDoHOUEu.js} +1 -1
- streamlit/static/static/js/{index.NE3kJsno.js → index.BJrY61fW.js} +1 -1
- streamlit/static/static/js/{index.9ahYhn9L.js → index.Bk2dieuB.js} +1 -1
- streamlit/static/static/js/{index.CPBpuLNa.js → index.BlpcPmc8.js} +1 -1
- streamlit/static/static/js/{index.DFJR7tFk.js → index.Bnv2GQ1f.js} +1 -1
- streamlit/static/static/js/{index.CeVeyA9j.js → index.BooesbgI.js} +1 -1
- streamlit/static/static/js/{index.D75DmXmJ.js → index.Bp2P-ne7.js} +1 -1
- streamlit/static/static/js/{index.Dj9pydGj.js → index.BpqJCHW4.js} +1 -1
- streamlit/static/static/js/{index.qG6NX4j3.js → index.BsajPDiD.js} +1 -1
- streamlit/static/static/js/{index.T6zTT7so.js → index.BzbL2a8R.js} +1 -1
- streamlit/static/static/js/{index.B1SRlRQI.js → index.C7tk-BaI.js} +1 -1
- streamlit/static/static/js/{index.Cz-wSZKK.js → index.CA2NGDaW.js} +1 -1
- streamlit/static/static/js/{index.CoEs3Tyr.js → index.CRdGuqu3.js} +1 -1
- streamlit/static/static/js/{index.DXwLRPNi.js → index.CT0nwqsw.js} +1 -1
- streamlit/static/static/js/{index.l2ZjmqZa.js → index.CWwqcOXB.js} +1 -1
- streamlit/static/static/js/{index.C9SZjgyE.js → index.CeEGQX9i.js} +1 -1
- streamlit/static/static/js/{index.BvuI_MOQ.js → index.CmBGzoYB.js} +1 -1
- streamlit/static/static/js/{index.CaDlXCxB.js → index.CzaH4EJh.js} +1 -1
- streamlit/static/static/js/{index.C51U-ytW.js → index.D39reA1n.js} +1 -1
- streamlit/static/static/js/{index.BQdNrQcI.js → index.DKS3g4Ws.js} +1 -1
- streamlit/static/static/js/{index.DYNcgXHh.js → index.D_Z8_2ei.js} +1 -1
- streamlit/static/static/js/{index.Dc-nqnmm.js → index.DbVBJOze.js} +1 -1
- streamlit/static/static/js/{index.BkUl8Uwz.js → index.DewKSDBK.js} +39 -39
- streamlit/static/static/js/{index.Bml5MH48.js → index.DipBpxzK.js} +1 -1
- streamlit/static/static/js/{index.lC8LhcmX.js → index.DoNPe-YW.js} +1 -1
- streamlit/static/static/js/{index.C4ApZ9VX.js → index.DwTevPv_.js} +1 -1
- streamlit/static/static/js/{index.8zBbwiSq.js → index.Dw_iEQ1s.js} +1 -1
- streamlit/static/static/js/{index.CaUiwEHb.js → index.Dz3G_3mZ.js} +1 -1
- streamlit/static/static/js/{index.45HlJMvy.js → index.WP3FKPhV.js} +1 -1
- streamlit/static/static/js/{index.lmhSYtGE.js → index.iV6t3ri-.js} +1 -1
- streamlit/static/static/js/{index.DZEEja3T.js → index.t3xwOrU9.js} +1 -1
- streamlit/static/static/js/{index.Cz5dPfTR.js → index.tbMYLMrS.js} +1 -1
- streamlit/static/static/js/index.xsH4HHeE.js +6 -0
- streamlit/static/static/js/{index.Br4Vls5z.js → index.z-3XVs6d.js} +1 -1
- streamlit/static/static/js/{input.AzemsQR7.js → input.B2MDikVk.js} +1 -1
- streamlit/static/static/js/{memory.BNnDm5qx.js → memory.BCb625DQ.js} +1 -1
- streamlit/static/static/js/{mergeWith.CnAe-pY8.js → mergeWith.COIRyAFl.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.CoO3Xzpl.js → number-overlay-editor.2CkzyF3w.js} +1 -1
- streamlit/static/static/js/{possibleConstructorReturn.-4k2karl.js → possibleConstructorReturn.3T2FklLD.js} +1 -1
- streamlit/static/static/js/{sandbox.B_lhrPSt.js → sandbox.Cc6yBPvx.js} +1 -1
- streamlit/static/static/js/{textarea.BXroYkeL.js → textarea.C7jOKez6.js} +1 -1
- streamlit/static/static/js/{timepicker.mhMg0du0.js → timepicker.BjMKxgZK.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.xDE9XBoI.js → toConsumableArray.BQ7m3eYw.js} +1 -1
- streamlit/static/static/js/{uniqueId.DPZFapqq.js → uniqueId.CJ7dn8nU.js} +1 -1
- streamlit/static/static/js/{useBasicWidgetState.DWXpUITX.js → useBasicWidgetState.QdMR1Kj8.js} +1 -1
- streamlit/static/static/js/{useOnInputChange.FMGxl8Ty.js → useOnInputChange.DppkR64F.js} +1 -1
- streamlit/static/static/js/{withFullScreenWrapper.cCJx5Did.js → withFullScreenWrapper.C2Ah-iZc.js} +1 -1
- streamlit/testing/v1/app_test.py +2 -2
- streamlit/testing/v1/element_tree.py +7 -7
- streamlit/type_util.py +2 -2
- streamlit/user_info.py +3 -3
- streamlit/watcher/event_based_path_watcher.py +14 -0
- streamlit/watcher/local_sources_watcher.py +43 -7
- streamlit/web/bootstrap.py +3 -3
- streamlit/web/cli.py +7 -7
- streamlit/web/server/media_file_handler.py +2 -2
- {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/RECORD +145 -145
- {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/WHEEL +1 -1
- streamlit/static/static/js/index.t--hEgTQ.js +0 -6
- {streamlit_nightly-1.44.2.dev20250427.data → streamlit_nightly-1.45.1.dev20250429.data}/scripts/streamlit.cmd +0 -0
- {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.44.2.dev20250427.dist-info → streamlit_nightly-1.45.1.dev20250429.dist-info}/top_level.txt +0 -0
streamlit/auth_util.py
CHANGED
@@ -40,7 +40,7 @@ class AuthCache:
|
|
40
40
|
|
41
41
|
# for set method, we are follow the same signature used in Authlib
|
42
42
|
# the expires_in is not used in our case
|
43
|
-
def set(self, key, value, expires_in):
|
43
|
+
def set(self, key, value, expires_in): # noqa: ARG002
|
44
44
|
self.cache[key] = value
|
45
45
|
|
46
46
|
def get_dict(self):
|
@@ -210,7 +210,7 @@ And if you're using Streamlit Cloud, add "pyarrow" to your requirements.txt."""
|
|
210
210
|
)
|
211
211
|
element.component_instance.id = computed_id
|
212
212
|
|
213
|
-
def deserialize_component(ui_value
|
213
|
+
def deserialize_component(ui_value):
|
214
214
|
# ui_value is an object from json, an ArrowTable proto, or a bytearray
|
215
215
|
return ui_value
|
216
216
|
|
streamlit/config.py
CHANGED
@@ -662,6 +662,20 @@ _create_option(
|
|
662
662
|
|
663
663
|
_create_section("server", "Settings for the Streamlit server")
|
664
664
|
|
665
|
+
|
666
|
+
_create_option(
|
667
|
+
"server.folderWatchList",
|
668
|
+
description="""
|
669
|
+
List of folders to watch for changes.
|
670
|
+
|
671
|
+
By default, Streamlit watches for files in the current working directory.
|
672
|
+
Use this parameter to specify additional folders to watch.
|
673
|
+
|
674
|
+
Note: This is a list of absolute paths.
|
675
|
+
""",
|
676
|
+
default_val=[],
|
677
|
+
)
|
678
|
+
|
665
679
|
_create_option(
|
666
680
|
"server.folderWatchBlacklist",
|
667
681
|
description="""
|
@@ -1530,8 +1544,8 @@ def get_config_options(
|
|
1530
1544
|
if not os.path.exists(filename):
|
1531
1545
|
continue
|
1532
1546
|
|
1533
|
-
with open(filename, encoding="utf-8") as
|
1534
|
-
file_contents =
|
1547
|
+
with open(filename, encoding="utf-8") as file:
|
1548
|
+
file_contents = file.read()
|
1535
1549
|
|
1536
1550
|
_update_config_with_toml(file_contents, filename)
|
1537
1551
|
|
@@ -1561,8 +1575,8 @@ def _check_conflicts() -> None:
|
|
1561
1575
|
|
1562
1576
|
# When using the Node server, we must always connect to 8501 (this is
|
1563
1577
|
# hard-coded in JS). Otherwise, the browser would decide what port to
|
1564
|
-
# connect to based on window.location.port, which in dev is going
|
1565
|
-
# be (3000)
|
1578
|
+
# connect to based on window.location.port, which in dev is going
|
1579
|
+
# to be (3000)
|
1566
1580
|
|
1567
1581
|
# Import logger locally to prevent circular references
|
1568
1582
|
from streamlit.logger import get_logger
|
streamlit/delta_generator.py
CHANGED
@@ -423,7 +423,6 @@ class DeltaGenerator(
|
|
423
423
|
delta_type: str,
|
424
424
|
element_proto: Message,
|
425
425
|
add_rows_metadata: AddRowsMetadata | None = None,
|
426
|
-
user_key: str | None = None,
|
427
426
|
) -> DeltaGenerator:
|
428
427
|
"""Create NewElement delta, fill it, and enqueue it.
|
429
428
|
|
@@ -435,8 +434,6 @@ class DeltaGenerator(
|
|
435
434
|
The actual proto in the NewElement type e.g. Alert/Button/Slider
|
436
435
|
add_rows_metadata : AddRowsMetadata or None
|
437
436
|
Metadata for the add_rows method
|
438
|
-
user_key : str or None
|
439
|
-
A custom key for the element provided by the user.
|
440
437
|
|
441
438
|
Returns
|
442
439
|
-------
|
streamlit/deprecation_util.py
CHANGED
@@ -200,7 +200,7 @@ def _create_deprecated_obj_wrapper(obj: TObj, show_warning: Callable[[], Any]) -
|
|
200
200
|
|
201
201
|
@staticmethod
|
202
202
|
def _make_magic_function_proxy(name):
|
203
|
-
def proxy(self, *args):
|
203
|
+
def proxy(self, *args): # noqa: ARG001
|
204
204
|
maybe_show_warning()
|
205
205
|
return getattr(obj, name)
|
206
206
|
|
streamlit/elements/arrow.py
CHANGED
@@ -160,7 +160,7 @@ class DataframeState(TypedDict, total=False):
|
|
160
160
|
class DataframeSelectionSerde:
|
161
161
|
"""DataframeSelectionSerde is used to serialize and deserialize the dataframe selection state."""
|
162
162
|
|
163
|
-
def deserialize(self, ui_value: str | None
|
163
|
+
def deserialize(self, ui_value: str | None) -> DataframeState:
|
164
164
|
empty_selection_state: DataframeState = {
|
165
165
|
"selection": {
|
166
166
|
"rows": [],
|
@@ -208,14 +208,14 @@ def parse_selection_mode(
|
|
208
208
|
)
|
209
209
|
|
210
210
|
parsed_selection_modes = []
|
211
|
-
for
|
212
|
-
if
|
211
|
+
for mode in selection_mode_set:
|
212
|
+
if mode == "single-row":
|
213
213
|
parsed_selection_modes.append(ArrowProto.SelectionMode.SINGLE_ROW)
|
214
|
-
elif
|
214
|
+
elif mode == "multi-row":
|
215
215
|
parsed_selection_modes.append(ArrowProto.SelectionMode.MULTI_ROW)
|
216
|
-
elif
|
216
|
+
elif mode == "single-column":
|
217
217
|
parsed_selection_modes.append(ArrowProto.SelectionMode.SINGLE_COLUMN)
|
218
|
-
elif
|
218
|
+
elif mode == "multi-column":
|
219
219
|
parsed_selection_modes.append(ArrowProto.SelectionMode.MULTI_COLUMN)
|
220
220
|
return set(parsed_selection_modes)
|
221
221
|
|
streamlit/elements/code.py
CHANGED
@@ -16,6 +16,7 @@ from __future__ import annotations
|
|
16
16
|
|
17
17
|
from typing import TYPE_CHECKING, cast
|
18
18
|
|
19
|
+
from streamlit.elements.lib.layout_utils import WidthWithoutContent, validate_width
|
19
20
|
from streamlit.proto.Code_pb2 import Code as CodeProto
|
20
21
|
from streamlit.runtime.metrics_util import gather_metrics
|
21
22
|
from streamlit.string_util import clean_text
|
@@ -35,6 +36,7 @@ class CodeMixin:
|
|
35
36
|
line_numbers: bool = False,
|
36
37
|
wrap_lines: bool = False,
|
37
38
|
height: int | None = None,
|
39
|
+
width: WidthWithoutContent = "stretch",
|
38
40
|
) -> DeltaGenerator:
|
39
41
|
"""Display a code block with optional syntax highlighting.
|
40
42
|
|
@@ -67,6 +69,11 @@ class CodeMixin:
|
|
67
69
|
its content. Vertical scrolling within the element is enabled when
|
68
70
|
the height does not accomodate all lines.
|
69
71
|
|
72
|
+
width : "stretch" or int
|
73
|
+
The width of the code block. This can be either:
|
74
|
+
- "stretch" (default): The code block will stretch to fill the container width
|
75
|
+
- An integer: The code block will have a fixed width in pixels
|
76
|
+
|
70
77
|
Examples
|
71
78
|
--------
|
72
79
|
>>> import streamlit as st
|
@@ -106,6 +113,14 @@ class CodeMixin:
|
|
106
113
|
code_proto.wrap_lines = wrap_lines
|
107
114
|
if height:
|
108
115
|
code_proto.height = height
|
116
|
+
|
117
|
+
# Set width configuration
|
118
|
+
validate_width(width)
|
119
|
+
if isinstance(width, int):
|
120
|
+
code_proto.width_config.pixel_width = width
|
121
|
+
else:
|
122
|
+
code_proto.width_config.use_stretch = True
|
123
|
+
|
109
124
|
return self.dg._enqueue("code", code_proto)
|
110
125
|
|
111
126
|
@property
|
@@ -91,10 +91,10 @@ def parse_selection_mode(
|
|
91
91
|
)
|
92
92
|
|
93
93
|
parsed_selection_modes = []
|
94
|
-
for
|
95
|
-
if
|
94
|
+
for mode in selection_mode_set:
|
95
|
+
if mode == "single-object":
|
96
96
|
parsed_selection_modes.append(PydeckProto.SelectionMode.SINGLE_OBJECT)
|
97
|
-
elif
|
97
|
+
elif mode == "multi-object":
|
98
98
|
parsed_selection_modes.append(PydeckProto.SelectionMode.MULTI_OBJECT)
|
99
99
|
return set(parsed_selection_modes)
|
100
100
|
|
@@ -233,7 +233,7 @@ class PydeckState(TypedDict, total=False):
|
|
233
233
|
class PydeckSelectionSerde:
|
234
234
|
"""PydeckSelectionSerde is used to serialize and deserialize the Pydeck selection state."""
|
235
235
|
|
236
|
-
def deserialize(self, ui_value: str | None
|
236
|
+
def deserialize(self, ui_value: str | None) -> PydeckState:
|
237
237
|
empty_selection_state: PydeckState = {
|
238
238
|
"selection": {
|
239
239
|
"indices": {},
|
@@ -97,7 +97,6 @@ def _dialog_decorator(
|
|
97
97
|
# if the dialog should be closed, st.rerun() has to be called
|
98
98
|
# (same behavior as with st.fragment)
|
99
99
|
_ = non_optional_func(*args, **kwargs)
|
100
|
-
return None
|
101
100
|
|
102
101
|
# the fragment decorator has multiple return types so that you can pass
|
103
102
|
# arguments to it. Here we know the return type, so we cast
|
streamlit/elements/doc_string.py
CHANGED
@@ -28,7 +28,7 @@ from streamlit.proto.DocString_pb2 import DocString as DocStringProto
|
|
28
28
|
from streamlit.proto.DocString_pb2 import Member as MemberProto
|
29
29
|
from streamlit.runtime.metrics_util import gather_metrics
|
30
30
|
from streamlit.runtime.scriptrunner.script_runner import (
|
31
|
-
__file__ as SCRIPTRUNNER_FILENAME,
|
31
|
+
__file__ as SCRIPTRUNNER_FILENAME, # noqa: N812
|
32
32
|
)
|
33
33
|
from streamlit.runtime.secrets import Secrets
|
34
34
|
from streamlit.string_util import is_mem_address_str
|
@@ -149,18 +149,14 @@ def _marshall(doc_string_proto: DocStringProto, obj: Any) -> None:
|
|
149
149
|
|
150
150
|
def _get_name(obj):
|
151
151
|
# Try to get the fully-qualified name of the object.
|
152
|
-
# For example:
|
153
|
-
#
|
154
|
-
#
|
155
|
-
# The name is bar.Baz
|
152
|
+
# For example: st.help(bar.Baz(123))
|
153
|
+
# The name is bar.Baz
|
156
154
|
name = getattr(obj, "__qualname__", None)
|
157
155
|
if name:
|
158
156
|
return name
|
159
157
|
|
160
158
|
# Try to get the name of the object.
|
161
|
-
# For example:
|
162
|
-
# st.help(bar.Baz(123))
|
163
|
-
#
|
159
|
+
# For example: st.help(bar.Baz(123))
|
164
160
|
# The name is Baz
|
165
161
|
return getattr(obj, "__name__", None)
|
166
162
|
|
@@ -175,10 +171,6 @@ def _get_signature(obj):
|
|
175
171
|
|
176
172
|
sig = ""
|
177
173
|
|
178
|
-
# TODO: Can we replace below with this?
|
179
|
-
# with contextlib.suppress(ValueError):
|
180
|
-
# sig = str(inspect.signature(obj))
|
181
|
-
|
182
174
|
try:
|
183
175
|
sig = str(inspect.signature(obj))
|
184
176
|
except ValueError:
|
@@ -248,20 +240,20 @@ def _get_variable_name_from_code_str(code):
|
|
248
240
|
|
249
241
|
# Example:
|
250
242
|
#
|
251
|
-
# tree = Module(
|
252
|
-
# body=[
|
253
|
-
# Expr(
|
254
|
-
# value=Call(
|
255
|
-
# args=[
|
256
|
-
# Name(id='the variable name')
|
257
|
-
# ],
|
258
|
-
# keywords=[
|
259
|
-
# ???
|
260
|
-
# ],
|
261
|
-
# )
|
262
|
-
# )
|
263
|
-
# ]
|
264
|
-
# )
|
243
|
+
# > tree = Module(
|
244
|
+
# > body=[
|
245
|
+
# > Expr(
|
246
|
+
# > value=Call(
|
247
|
+
# > args=[
|
248
|
+
# > Name(id='the variable name')
|
249
|
+
# > ],
|
250
|
+
# > keywords=[
|
251
|
+
# > ???
|
252
|
+
# > ],
|
253
|
+
# > )
|
254
|
+
# > )
|
255
|
+
# > ]
|
256
|
+
# > )
|
265
257
|
|
266
258
|
# Check if this is an magic call (i.e. it's not st.help or st.write).
|
267
259
|
# If that's the case, just clean it up and return it.
|
streamlit/elements/image.py
CHANGED
@@ -167,15 +167,14 @@ class ImageMixin:
|
|
167
167
|
elif use_column_width == "never" or use_column_width is False:
|
168
168
|
image_width = WidthBehavior.ORIGINAL
|
169
169
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
image_width = WidthBehavior.MIN_IMAGE_OR_CONTAINER
|
170
|
+
elif use_container_width is True:
|
171
|
+
image_width = WidthBehavior.MAX_IMAGE_OR_CONTAINER
|
172
|
+
elif image_width is not None and image_width > 0:
|
173
|
+
# Use the given width. It will be capped on the frontend if it
|
174
|
+
# exceeds the container width.
|
175
|
+
pass
|
176
|
+
elif use_container_width is False:
|
177
|
+
image_width = WidthBehavior.MIN_IMAGE_OR_CONTAINER
|
179
178
|
|
180
179
|
image_list_proto = ImageListProto()
|
181
180
|
marshall_images(
|
@@ -366,8 +366,8 @@ def _infer_vegalite_type(
|
|
366
366
|
return "quantitative"
|
367
367
|
|
368
368
|
elif typ == "categorical" and data.cat.ordered:
|
369
|
-
#
|
370
|
-
# return ("ordinal", data.cat.categories.tolist())
|
369
|
+
# The original code returns a tuple here:
|
370
|
+
# return ("ordinal", data.cat.categories.tolist()) # noqa: ERA001
|
371
371
|
# But returning the tuple here isn't compatible with our
|
372
372
|
# built-in chart implementation. And it also doesn't seem to be necessary.
|
373
373
|
# Altair already extracts the correct sort order somewhere else.
|
@@ -387,11 +387,11 @@ def _infer_vegalite_type(
|
|
387
387
|
return "temporal"
|
388
388
|
else:
|
389
389
|
# STREAMLIT MOD: I commented this out since Streamlit doesn't use warnings.warn.
|
390
|
-
# warnings.warn(
|
391
|
-
# "I don't know how to infer vegalite type from '{}'. "
|
392
|
-
# "Defaulting to nominal.".format(typ),
|
393
|
-
# stacklevel=1,
|
394
|
-
# )
|
390
|
+
# > warnings.warn(
|
391
|
+
# > "I don't know how to infer vegalite type from '{}'. "
|
392
|
+
# > "Defaulting to nominal.".format(typ),
|
393
|
+
# > stacklevel=1,
|
394
|
+
# > )
|
395
395
|
return "nominal"
|
396
396
|
|
397
397
|
|
@@ -551,7 +551,7 @@ def _melt_data(
|
|
551
551
|
)
|
552
552
|
|
553
553
|
# Arrow has problems with object types after melting two different dtypes
|
554
|
-
# pyarrow.lib.ArrowTypeError: "Expected a <TYPE> object, got a object"
|
554
|
+
# > pyarrow.lib.ArrowTypeError: "Expected a <TYPE> object, got a object"
|
555
555
|
fixed_df = dataframe_util.fix_arrow_incompatible_column_types(
|
556
556
|
melted_df,
|
557
557
|
selected_columns=[
|
@@ -188,7 +188,7 @@ def _determine_data_kind_via_arrow(field: pa.Field) -> ColumnDataKind:
|
|
188
188
|
|
189
189
|
# Interval does not seem to work correctly:
|
190
190
|
# if pa.types.is_interval(field_type):
|
191
|
-
# return ColumnDataKind.INTERVAL
|
191
|
+
# return ColumnDataKind.INTERVAL # noqa: ERA001
|
192
192
|
|
193
193
|
if pa.types.is_binary(field_type):
|
194
194
|
return ColumnDataKind.BYTES
|
@@ -97,12 +97,12 @@ def _validate_image_format_string(
|
|
97
97
|
- For all other strings, return "PNG" if the image has an alpha channel,
|
98
98
|
"GIF" if the image is a GIF, and "JPEG" otherwise.
|
99
99
|
"""
|
100
|
-
|
101
|
-
if
|
102
|
-
return cast("ImageFormat",
|
100
|
+
img_format = format.upper()
|
101
|
+
if img_format in {"JPEG", "PNG"}:
|
102
|
+
return cast("ImageFormat", img_format)
|
103
103
|
|
104
104
|
# We are forgiving on the spelling of JPEG
|
105
|
-
if
|
105
|
+
if img_format == "JPG":
|
106
106
|
return "JPEG"
|
107
107
|
|
108
108
|
pil_image: PILImage
|
@@ -122,7 +122,7 @@ def _validate_image_format_string(
|
|
122
122
|
return "JPEG"
|
123
123
|
|
124
124
|
|
125
|
-
def
|
125
|
+
def _pil_to_bytes(
|
126
126
|
image: PILImage,
|
127
127
|
format: ImageFormat = "JPEG",
|
128
128
|
quality: int = 100,
|
@@ -139,7 +139,7 @@ def _PIL_to_bytes(
|
|
139
139
|
return tmp.getvalue()
|
140
140
|
|
141
141
|
|
142
|
-
def
|
142
|
+
def _bytesio_to_bytes(data: io.BytesIO) -> bytes:
|
143
143
|
data.seek(0)
|
144
144
|
return data.getvalue()
|
145
145
|
|
@@ -149,9 +149,9 @@ def _np_array_to_bytes(array: npt.NDArray[Any], output_format: str = "JPEG") ->
|
|
149
149
|
from PIL import Image
|
150
150
|
|
151
151
|
img = Image.fromarray(array.astype(np.uint8))
|
152
|
-
|
152
|
+
img_format = _validate_image_format_string(img, output_format)
|
153
153
|
|
154
|
-
return
|
154
|
+
return _pil_to_bytes(img, img_format)
|
155
155
|
|
156
156
|
|
157
157
|
def _verify_np_shape(array: npt.NDArray[Any]) -> npt.NDArray[Any]:
|
@@ -199,11 +199,11 @@ def _ensure_image_size_and_format(
|
|
199
199
|
# versions. The types don't seem to reflect this, though, hence the type: ignore
|
200
200
|
# below.
|
201
201
|
pil_image = pil_image.resize((width, new_height), resample=Image.BILINEAR) # type: ignore[attr-defined]
|
202
|
-
return
|
202
|
+
return _pil_to_bytes(pil_image, format=image_format, quality=90)
|
203
203
|
|
204
204
|
if pil_image.format != image_format:
|
205
205
|
# We need to reformat the image.
|
206
|
-
return
|
206
|
+
return _pil_to_bytes(pil_image, format=image_format, quality=90)
|
207
207
|
|
208
208
|
# No resizing or reformatting necessary - return the original bytes.
|
209
209
|
return image_data
|
@@ -216,16 +216,13 @@ def _clip_image(image: npt.NDArray[Any], clamp: bool) -> npt.NDArray[Any]:
|
|
216
216
|
if issubclass(image.dtype.type, np.floating):
|
217
217
|
if clamp:
|
218
218
|
data = np.clip(image, 0, 1.0)
|
219
|
-
|
220
|
-
|
221
|
-
raise RuntimeError("Data is outside [0.0, 1.0] and clamp is not set.")
|
219
|
+
elif np.amin(image) < 0.0 or np.amax(image) > 1.0:
|
220
|
+
raise RuntimeError("Data is outside [0.0, 1.0] and clamp is not set.")
|
222
221
|
data = data * 255
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
if np.amin(image) < 0 or np.amax(image) > 255:
|
228
|
-
raise RuntimeError("Data is outside [0, 255] and clamp is not set.")
|
222
|
+
elif clamp:
|
223
|
+
data = np.clip(image, 0, 255)
|
224
|
+
elif np.amin(image) < 0 or np.amax(image) > 255:
|
225
|
+
raise RuntimeError("Data is outside [0, 255] and clamp is not set.")
|
229
226
|
return data
|
230
227
|
|
231
228
|
|
@@ -301,14 +298,14 @@ def image_to_url(
|
|
301
298
|
|
302
299
|
# PIL Images
|
303
300
|
elif isinstance(image, (ImageFile.ImageFile, Image.Image)):
|
304
|
-
|
305
|
-
image_data =
|
301
|
+
img_format = _validate_image_format_string(image, output_format)
|
302
|
+
image_data = _pil_to_bytes(image, img_format)
|
306
303
|
|
307
304
|
# BytesIO
|
308
305
|
# Note: This doesn't support SVG. We could convert to png (cairosvg.svg2png)
|
309
306
|
# or just decode BytesIO to string and handle that way.
|
310
307
|
elif isinstance(image, io.BytesIO):
|
311
|
-
image_data =
|
308
|
+
image_data = _bytesio_to_bytes(image)
|
312
309
|
|
313
310
|
# Numpy Arrays (ie opencv)
|
314
311
|
elif isinstance(image, np.ndarray):
|
@@ -430,15 +427,17 @@ def marshall_images(
|
|
430
427
|
|
431
428
|
proto_imgs.width = int(width)
|
432
429
|
# Each image in an image list needs to be kept track of at its own coordinates.
|
433
|
-
for coord_suffix, (
|
430
|
+
for coord_suffix, (single_image, single_caption) in enumerate(
|
431
|
+
zip(images, captions)
|
432
|
+
):
|
434
433
|
proto_img = proto_imgs.imgs.add()
|
435
|
-
if
|
436
|
-
proto_img.caption = str(
|
434
|
+
if single_caption is not None:
|
435
|
+
proto_img.caption = str(single_caption)
|
437
436
|
|
438
437
|
# We use the index of the image in the input image list to identify this image inside
|
439
438
|
# MediaFileManager. For this, we just add the index to the image's "coordinates".
|
440
439
|
image_id = "%s-%i" % (coordinates, coord_suffix)
|
441
440
|
|
442
441
|
proto_img.url = image_to_url(
|
443
|
-
|
442
|
+
single_image, width, clamp, channels, output_format, image_id
|
444
443
|
)
|
@@ -196,13 +196,13 @@ def _pandas_style_to_css(
|
|
196
196
|
|
197
197
|
# In pandas >= 1.1.0
|
198
198
|
# translated_style["cellstyle"] has the following shape:
|
199
|
-
# [
|
200
|
-
# {
|
201
|
-
# "props": [("color", " black"), ("background-color", "orange"), ("", "")],
|
202
|
-
# "selectors": ["row0_col0"]
|
203
|
-
# }
|
204
|
-
# ...
|
205
|
-
# ]
|
199
|
+
# > [
|
200
|
+
# > {
|
201
|
+
# > "props": [("color", " black"), ("background-color", "orange"), ("", "")],
|
202
|
+
# > "selectors": ["row0_col0"]
|
203
|
+
# > }
|
204
|
+
# > ...
|
205
|
+
# > ]
|
206
206
|
if style_type == "table_styles":
|
207
207
|
cell_selectors = [style["selector"]]
|
208
208
|
else:
|
streamlit/elements/map.py
CHANGED
@@ -20,8 +20,8 @@ import copy
|
|
20
20
|
import json
|
21
21
|
from typing import TYPE_CHECKING, Any, Final, cast
|
22
22
|
|
23
|
-
import streamlit.elements.deck_gl_json_chart as deck_gl_json_chart
|
24
23
|
from streamlit import config, dataframe_util
|
24
|
+
from streamlit.elements import deck_gl_json_chart
|
25
25
|
from streamlit.elements.lib.color_util import (
|
26
26
|
Color,
|
27
27
|
IntColorTuple,
|
@@ -230,7 +230,7 @@ class MapMixin:
|
|
230
230
|
#
|
231
231
|
# For reference, this was the docstring for map_style:
|
232
232
|
#
|
233
|
-
# map_style : str
|
233
|
+
# map_style : str, None
|
234
234
|
# One of Mapbox's map style URLs. A full list can be found here:
|
235
235
|
# https://docs.mapbox.com/api/maps/styles/#mapbox-styles
|
236
236
|
#
|
@@ -214,7 +214,7 @@ class PlotlyChartSelectionSerde:
|
|
214
214
|
selection state.
|
215
215
|
"""
|
216
216
|
|
217
|
-
def deserialize(self, ui_value: str | None
|
217
|
+
def deserialize(self, ui_value: str | None) -> PlotlyState:
|
218
218
|
empty_selection_state: PlotlyState = {
|
219
219
|
"selection": {
|
220
220
|
"points": [],
|
@@ -257,12 +257,12 @@ def parse_selection_mode(
|
|
257
257
|
)
|
258
258
|
|
259
259
|
parsed_selection_modes = []
|
260
|
-
for
|
261
|
-
if
|
260
|
+
for mode in selection_mode_set:
|
261
|
+
if mode == "points":
|
262
262
|
parsed_selection_modes.append(PlotlyChartProto.SelectionMode.POINTS)
|
263
|
-
elif
|
263
|
+
elif mode == "lasso":
|
264
264
|
parsed_selection_modes.append(PlotlyChartProto.SelectionMode.LASSO)
|
265
|
-
elif
|
265
|
+
elif mode == "box":
|
266
266
|
parsed_selection_modes.append(PlotlyChartProto.SelectionMode.BOX)
|
267
267
|
return set(parsed_selection_modes)
|
268
268
|
|
@@ -33,8 +33,8 @@ from typing import (
|
|
33
33
|
|
34
34
|
from typing_extensions import TypeAlias
|
35
35
|
|
36
|
-
import streamlit.elements.lib.dicttools as dicttools
|
37
36
|
from streamlit import dataframe_util, type_util
|
37
|
+
from streamlit.elements.lib import dicttools
|
38
38
|
from streamlit.elements.lib.built_in_chart_utils import (
|
39
39
|
AddRowsMetadata,
|
40
40
|
ChartStackType,
|
@@ -227,7 +227,7 @@ class VegaLiteStateSerde:
|
|
227
227
|
|
228
228
|
selection_parameters: Sequence[str]
|
229
229
|
|
230
|
-
def deserialize(self, ui_value: str | None
|
230
|
+
def deserialize(self, ui_value: str | None) -> VegaLiteState:
|
231
231
|
empty_selection_state: VegaLiteState = {
|
232
232
|
"selection": AttributeDictionary(
|
233
233
|
# Initialize the select state with empty dictionaries for each selection parameter.
|
@@ -256,8 +256,8 @@ def _prepare_vega_lite_spec(
|
|
256
256
|
**kwargs,
|
257
257
|
) -> VegaLiteSpec:
|
258
258
|
if kwargs:
|
259
|
-
# Support passing in kwargs.
|
260
|
-
#
|
259
|
+
# Support passing in kwargs.
|
260
|
+
# > marshall(proto, {foo: 'bar'}, baz='boz')
|
261
261
|
# Merge spec with unflattened kwargs, where kwargs take precedence.
|
262
262
|
# This only works for string keys, but kwarg keys are strings anyways.
|
263
263
|
spec = dict(spec, **dicttools.unflatten(kwargs, _CHANNELS))
|
@@ -313,10 +313,10 @@ def _marshall_chart_data(
|
|
313
313
|
del spec["datasets"]
|
314
314
|
|
315
315
|
# Pull data out of spec dict when it's in a top-level 'data' key:
|
316
|
-
#
|
317
|
-
#
|
318
|
-
#
|
319
|
-
#
|
316
|
+
# > {data: df}
|
317
|
+
# > {data: {values: df, ...}}
|
318
|
+
# > {data: {url: 'url'}}
|
319
|
+
# > {data: {name: 'foo'}}
|
320
320
|
if "data" in spec:
|
321
321
|
data_spec = spec["data"]
|
322
322
|
|
@@ -73,7 +73,7 @@ class AudioInputSerde:
|
|
73
73
|
return state_proto
|
74
74
|
|
75
75
|
def deserialize(
|
76
|
-
self, ui_value: FileUploaderStateProto | None
|
76
|
+
self, ui_value: FileUploaderStateProto | None
|
77
77
|
) -> SomeUploadedAudioFile:
|
78
78
|
upload_files = _get_upload_files(ui_value)
|
79
79
|
if len(upload_files) == 0:
|
@@ -80,7 +80,7 @@ class ButtonSerde:
|
|
80
80
|
def serialize(self, v: bool) -> bool:
|
81
81
|
return bool(v)
|
82
82
|
|
83
|
-
def deserialize(self, ui_value: bool | None
|
83
|
+
def deserialize(self, ui_value: bool | None) -> bool:
|
84
84
|
return ui_value or False
|
85
85
|
|
86
86
|
|
@@ -799,15 +799,16 @@ class ButtonMixin:
|
|
799
799
|
) -> bool:
|
800
800
|
key = to_key(key)
|
801
801
|
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
802
|
+
on_click_callback: WidgetCallback | None = (
|
803
|
+
None
|
804
|
+
if on_click is None or on_click in {"ignore", "rerun"}
|
805
|
+
else cast("WidgetCallback", on_click)
|
806
|
+
)
|
806
807
|
|
807
808
|
check_widget_policies(
|
808
809
|
self.dg,
|
809
810
|
key,
|
810
|
-
on_click_callback,
|
811
|
+
on_change=on_click_callback,
|
811
812
|
default_value=None,
|
812
813
|
writes_allowed=False,
|
813
814
|
)
|